package com.hksj.lntm.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hksj.base.service.DefaultDeviceService;
import com.hksj.cbm.entity.DeviceInstance;
import com.hksj.cbm.entity.DeviceMetadataParseInfo;
import com.hksj.cbm.mapper.DeviceMetadataParseInfoMapper;
import com.hksj.cbm.service.DeviceInstanceService;
import com.hksj.common.core.common.Constants;
import com.hksj.common.core.common.DevicePropertyConstants;
import com.hksj.common.core.common.SpecialityModelCodeEnum;
import com.hksj.common.core.util.DateUtil;
import com.hksj.common.core.util.EasyExcelUtil;
import com.hksj.lntm.dto.LiquidNitrogenDeviceDTO;
import com.hksj.lntm.dto.LiquidNitrogenDeviceHistoryDTO;
import com.hksj.lntm.mapper.LiquidNitrogenDeviceMapper;
import com.hksj.lntm.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author fjt
 * @data 2024/11/11 8:52
 * @describe
 */
@Service
public class LiquidNitrogenDeviceService {


    @Autowired
    private LiquidNitrogenDeviceMapper liquidNitrogenDeviceMapper;
    @Autowired
    private DeviceMetadataParseInfoMapper deviceMetadataParseInfoMapper;
    @Autowired
    private DeviceInstanceService deviceInstanceService;
    @Autowired
    private DefaultDeviceService defaultDeviceService;




    /**
     * 分页查询液氮罐设备列表
     * @param dto
     * @return
     */
    public IPage<LiquidNitrogenDeviceVO> queryLiquidNitrogenDeviceByPage(LiquidNitrogenDeviceDTO dto){
        dto.setCode(SpecialityModelCodeEnum.liquid_nitrogen.getCode());
        IPage<LiquidNitrogenDeviceVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<LiquidNitrogenDeviceVO> list = liquidNitrogenDeviceMapper.queryLiquidNitrogenDeviceByPage(page, dto);
        if (CollUtil.isEmpty(list)){
            return page;
        }
        List<String> deviceIdList = list.stream().map(LiquidNitrogenDeviceVO::getDeviceId).collect(Collectors.toList());

        // 2.获取每个设备检测指标的当前值
        LambdaQueryWrapper<DeviceMetadataParseInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(DeviceMetadataParseInfo::getDeviceId, deviceIdList);
        List<DeviceMetadataParseInfo> deviceMetadataParseInfoList = deviceMetadataParseInfoMapper.selectList(queryWrapper);
        if (CollUtil.isEmpty(deviceMetadataParseInfoList)){
            page.setRecords(list);
            return page;
        }
        // 设备id : List<DeviceMetadataParseInfo>
        Map<String, List<DeviceMetadataParseInfo>> deviceMetadataParseInfoMap = deviceMetadataParseInfoList.stream().collect(
                Collectors.groupingBy(DeviceMetadataParseInfo::getDeviceId));

        // 3.查询每个设备监测指标的报警情况
        List<PropertyModelVO> propertyModelVOList = liquidNitrogenDeviceMapper.queryAlarmByDeviceIdList(deviceIdList);
        Map<String, Integer> deviceAlarmStatusMap = new HashMap<>();
        if (CollUtil.isNotEmpty(propertyModelVOList)){
            deviceAlarmStatusMap = propertyModelVOList.stream().collect(
                    Collectors.toMap(r -> r.getDeviceId() + "-" + r.getProperty(), r -> r.getStatus()));
        }

        // 4.组装设备返回数据
        for(LiquidNitrogenDeviceVO deviceVO : list){
            Integer deviceAlarmStatus = 1;
            String deviceId = deviceVO.getDeviceId();

            List<DeviceMetadataParseInfo> parseInfoList = deviceMetadataParseInfoMap.get(deviceId);
            // 当前设备有最新上报数据
            if (CollUtil.isNotEmpty(parseInfoList)){
                List<PropertyModelVO> propertyList = new ArrayList<>(parseInfoList.size());

                for(DeviceMetadataParseInfo parseInfo : parseInfoList){
                    PropertyModelVO propertyModelVO = PropertyModelVO.builder().deviceId(deviceId)
                            .property(parseInfo.getProperty()).propertyName(parseInfo.getPropertyName())
                            .value(String.format("%.1f", parseInfo.getNumberValue())).unit(parseInfo.getUnit()).build();

                    Integer status = ObjectUtil.isNotNull(deviceAlarmStatusMap.get(deviceId + "-" + parseInfo.getProperty())) ?
                            deviceAlarmStatusMap.get(deviceId + "-" + parseInfo.getProperty()) : 2;
                    propertyModelVO.setStatus(status);
                    propertyList.add(propertyModelVO);

                    // 0=报警中
                    if (Constants.ZERO.equals(status)){
                        deviceAlarmStatus = 0;
                    }
                }

                // 同一个设备，不同property的属性是同一次上报的
                deviceVO.setCreateTime(parseInfoList.get(0).getCreateTime());
                deviceVO.setPropertyModelVOList(propertyList);
            }

            // 设置设备的序号，排序规则：报警设备靠前，在线设备次之，离线最次
            if (Constants.ZERO.equals(deviceAlarmStatus)){
                deviceVO.setSort(0);
            }else {
                if (ObjectUtil.equals("online", deviceVO.getState())){
                    deviceVO.setSort(1);
                }
                if (ObjectUtil.equals("offline", deviceVO.getState())){
                    deviceVO.setSort(2);
                }
                if (ObjectUtil.equals("notActive", deviceVO.getState())){
                    deviceVO.setSort(3);
                }
            }
        }
        // 按sort升序排序，sort相同的按createTime降薪排序
        list = list.stream().sorted(Comparator.comparing(LiquidNitrogenDeviceVO::getSort, Comparator.naturalOrder()))
                .collect(Collectors.toList());
        page.setRecords(list);
        return page;
    }


    /**
     * 查询指定液氮罐设备历史监测指标趋势图
     * @param dto
     * @return
     */
    public List<LiquidNitrogenDeviceHistoryVO> queryLiquidNitrogenDeviceHistoryCurve(LiquidNitrogenDeviceHistoryDTO dto){
        DeviceInstance deviceInstance = deviceInstanceService.getById(dto.getDeviceId());
        Assert.notNull(deviceInstance, "设备信息表中不存在此设备");
        // 获取数据表名称
        String tableName = defaultDeviceService.getTableName(deviceInstance.getProductId());
        dto.setStartTime(DateUtil.getYmdHms(dto.getStartTimeStr() + " 00:00:00"));
        dto.setEndTime(DateUtil.getYmdHms(dto.getEndTimeStr() + " 23:59:59"));
        List<LiquidNitrogenDeviceHistoryDataVO> list =  liquidNitrogenDeviceMapper.LiquidNitrogenDeviceHistoryList(dto, tableName);
        if (CollUtil.isEmpty(list)){
            return null;
        }
        Map<String, List<LiquidNitrogenDeviceHistoryDataVO>> map = list.stream().collect(
                Collectors.groupingBy(p -> p.getDeviceId() + "-" + p.getProperty() + "-" + p.getPropertyName()));

        List<LiquidNitrogenDeviceHistoryVO> voList = new ArrayList<>(map.size());
        for(Map.Entry<String, List<LiquidNitrogenDeviceHistoryDataVO>> entry : map.entrySet()){
            String[] keys = entry.getKey().split("-");
            LiquidNitrogenDeviceHistoryVO liquidNitrogenDeviceHistoryVO = new LiquidNitrogenDeviceHistoryVO();
            liquidNitrogenDeviceHistoryVO.setDeviceId(keys[0]);
            liquidNitrogenDeviceHistoryVO.setProperty(keys[1]);
            liquidNitrogenDeviceHistoryVO.setPropertyName(keys[2]);

            List<LiquidNitrogenDeviceHistoryDataVO> dataVOList = entry.getValue();
            List<LiquidNitrogenDeviceHistoryVO.HistoryDataVO> historyDataVOList = new ArrayList<>(dataVOList.size());
            dataVOList.forEach(vo -> {
                LiquidNitrogenDeviceHistoryVO.HistoryDataVO dataVO = new LiquidNitrogenDeviceHistoryVO.HistoryDataVO();
                dataVO.setNumberValue(vo.getNumberValue());
                dataVO.setCreateTime(vo.getCreateTime());
                historyDataVOList.add(dataVO);
            });

            liquidNitrogenDeviceHistoryVO.setHistoryDataVOList(historyDataVOList);
            voList.add(liquidNitrogenDeviceHistoryVO);
        }
        return voList;
    }


    /**
     * 分页查询指定液氮罐设备历史监测指标详情
     * @param dto
     * @return
     */
    public IPage<LiquidNitrogenDeviceHistoryInfoVO> pageDeviceHistory(LiquidNitrogenDeviceHistoryDTO dto){
        DeviceInstance deviceInstance = deviceInstanceService.getById(dto.getDeviceId());
        Assert.notNull(deviceInstance, "设备信息表中不存在此设备");
        // 获取数据表名称
        String tableName = defaultDeviceService.getTableName(deviceInstance.getProductId());
        dto.setStartTime(DateUtil.getYmdHms(dto.getStartTimeStr() + " 00:00:00"));
        dto.setEndTime(DateUtil.getYmdHms(dto.getEndTimeStr() + " 23:59:59"));
        dto.setProperty(DevicePropertyConstants.liquid_nitrogen_temperature);

        // 查询数据总条数
        Long count = liquidNitrogenDeviceMapper.count(dto, tableName);
        // 查询瓶内温度
        List<LiquidNitrogenDeviceHistoryDataVO> tempList = liquidNitrogenDeviceMapper.pageDeviceHistoryByProperty(dto, tableName);

        // 查询液位深度
        dto.setProperty(DevicePropertyConstants.liquid_nitrogen_depth);
        List<LiquidNitrogenDeviceHistoryDataVO> depthList = liquidNitrogenDeviceMapper.pageDeviceHistoryByProperty(dto, tableName);

        // 根据时间匹配进行合并数据
        List<LiquidNitrogenDeviceHistoryInfoVO> voList = new ArrayList<>(tempList.size());
        for (LiquidNitrogenDeviceHistoryDataVO tempDataVO : tempList){
            LiquidNitrogenDeviceHistoryInfoVO vo = LiquidNitrogenDeviceHistoryInfoVO.builder()
                    .temperature(tempDataVO.getNumberValue()).createTime(tempDataVO.getCreateTime()).build();

            for(LiquidNitrogenDeviceHistoryDataVO depthDataVO : depthList){
                if (ObjectUtil.equals(tempDataVO.getCreateTime(), depthDataVO.getCreateTime())){
                    vo.setDepth(depthDataVO.getNumberValue());
                    break;
                }
            }
            voList.add(vo);
        }

        // 把没有匹配到时间的液位深度数据，追加到voList中
        for(LiquidNitrogenDeviceHistoryDataVO depthVO : depthList){
            boolean notExist = true;
            for(LiquidNitrogenDeviceHistoryInfoVO infoVO : voList){
                if (ObjectUtil.equals(depthVO.getCreateTime(), infoVO.getCreateTime())){
                    notExist = false;
                    break;
                }
            }
            if (notExist){
                LiquidNitrogenDeviceHistoryInfoVO vo = LiquidNitrogenDeviceHistoryInfoVO.builder()
                        .depth(depthVO.getNumberValue()).createTime(depthVO.getCreateTime()).build();
                voList.add(vo);
            }
        }

        Page<LiquidNitrogenDeviceHistoryInfoVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page.setTotal(count);
        page.setRecords(voList);
        return page;
    }


    /**
     * 导出指定液氮罐设备历史监测指标详情
     * @param response
     * @param dto
     */
    public void exportList(HttpServletResponse response, LiquidNitrogenDeviceHistoryDTO dto){
        DeviceInstance deviceInstance = deviceInstanceService.getById(dto.getDeviceId());
        Assert.notNull(deviceInstance, "设备信息表中不存在此设备");
        // 获取数据表名称
        String tableName = defaultDeviceService.getTableName(deviceInstance.getProductId());
        dto.setStartTime(DateUtil.getYmdHms(dto.getStartTimeStr() + " 00:00:00"));
        dto.setEndTime(DateUtil.getYmdHms(dto.getEndTimeStr() + " 23:59:59"));
        // 不使用分页
        dto.setDisAblePage(true);

        // 查询瓶内温度
        dto.setProperty(DevicePropertyConstants.liquid_nitrogen_temperature);
        List<LiquidNitrogenDeviceHistoryDataVO> tempList = liquidNitrogenDeviceMapper.pageDeviceHistoryByProperty(dto, tableName);
        // 查询液位深度
        dto.setProperty(DevicePropertyConstants.liquid_nitrogen_depth);
        List<LiquidNitrogenDeviceHistoryDataVO> depthList = liquidNitrogenDeviceMapper.pageDeviceHistoryByProperty(dto, tableName);

        // 根据时间匹配进行合并数据
        List<LiquidNitrogenDeviceHistoryInfoVO> voList = new ArrayList<>(tempList.size());
        for (LiquidNitrogenDeviceHistoryDataVO tempDataVO : tempList){
            LiquidNitrogenDeviceHistoryInfoVO vo = LiquidNitrogenDeviceHistoryInfoVO.builder()
                    .temperature(tempDataVO.getNumberValue()).createTime(tempDataVO.getCreateTime()).build();

            for(LiquidNitrogenDeviceHistoryDataVO depthDataVO : depthList){
                if (ObjectUtil.equals(tempDataVO.getCreateTime(), depthDataVO.getCreateTime())){
                    vo.setDepth(depthDataVO.getNumberValue());
                    break;
                }
            }
            voList.add(vo);
        }

        // 把没有匹配到时间的液位深度数据，追加到voList中
        for(LiquidNitrogenDeviceHistoryDataVO depthVO : depthList){
            boolean notExist = true;
            for(LiquidNitrogenDeviceHistoryInfoVO infoVO : voList){
                if (ObjectUtil.equals(depthVO.getCreateTime(), infoVO.getCreateTime())){
                    notExist = false;
                    break;
                }
            }
            if (notExist){
                LiquidNitrogenDeviceHistoryInfoVO vo = LiquidNitrogenDeviceHistoryInfoVO.builder()
                        .depth(depthVO.getNumberValue()).createTime(depthVO.getCreateTime()).build();
                voList.add(vo);
            }
        }

        String fileName = new StringBuffer().append("液氮罐历史监测记录").append(DateUtil.getYmdHms()).append(".xlsx").toString();
        EasyExcelUtil.exportExcelData(response, fileName, voList, LiquidNitrogenDeviceHistoryInfoVO.class);
    }


}
